package cn.edu.neusoft.demo.hospital2.Service.impl;

import cn.edu.neusoft.demo.hospital2.Dao.DepartmentDao;
import cn.edu.neusoft.demo.hospital2.Dao.RoomDao;
import cn.edu.neusoft.demo.hospital2.Dao.SpecialClinicDao;
import cn.edu.neusoft.demo.hospital2.Service.DepartmentService;
import cn.edu.neusoft.demo.hospital2.pojo.Department;
import cn.edu.neusoft.demo.hospital2.pojo.Room;
import cn.edu.neusoft.demo.hospital2.pojo.SpecialClinic;
import cn.edu.neusoft.demo.hospital2.pojo.dto.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class DepartmentServiceImpl implements DepartmentService {
    private static final Logger logger = LoggerFactory.getLogger(DepartmentServiceImpl.class);

    @Autowired
    private DepartmentDao departmentDao;
    @Autowired
    private RoomDao roomDao;
    @Autowired
    private SpecialClinicDao specialClinicDao;

    public DepartmentServiceImpl(DepartmentDao departmentDao,
                                 RoomDao roomDao,
                                 SpecialClinicDao specialClinicDao) {
        this.departmentDao = departmentDao;
        this.roomDao = roomDao;
        this.specialClinicDao = specialClinicDao;
    }

    @Override
    public List<DepartmentTreeDTO> getDepartmentTree() {
        // 查询所有一级科室
        List<Department> level1Depts = departmentDao.selectTopLevelDepartments();

        return level1Depts.stream().map(dept -> buildDepartmentTreeDTO(dept)).collect(Collectors.toList());
    }

    private DepartmentTreeDTO buildDepartmentTreeDTO(Department department) {
        DepartmentTreeDTO treeDTO = new DepartmentTreeDTO();
        treeDTO.setDepartment(convertToDTO(department));

        // 查询子科室
        List<Department> children = departmentDao.selectChildrenByParentId(department.getDepartmentId());
        treeDTO.setChildren(children.stream()
                .map(this::buildDepartmentTreeDTO)
                .collect(Collectors.toList()));

        // 查询关联诊室
        List<Room> rooms = roomDao.selectRoomsByDepartmentId(department.getDepartmentId());
        treeDTO.setRooms(rooms.stream()
                .map(this::convertToRoomDTO)
                .collect(Collectors.toList()));

        // 查询关联特色门诊
        List<SpecialClinic> clinics = specialClinicDao.getSpecialClinicsByDepartmentId(department.getDepartmentId());
        treeDTO.setClinics(clinics.stream()
                .map(this::convertToClinicDTO)
                .collect(Collectors.toList()));

        return treeDTO;
    }

    @Override
    public DepartmentDTO getDepartmentById(Integer id) {
        Department department = departmentDao.selectDepartmentById(id);
        if (department == null) {
            throw new RuntimeException("科室不存在");
        }
        return convertToDTO(department);
    }

    @Override
    @Transactional
    public boolean createDepartment(DepartmentCreateDTO dto) {
        // 验证父级科室是否存在
        if (dto.getLevel() == 2 && dto.getParentId() != null) {
            Department parent = departmentDao.selectDepartmentById(dto.getParentId());
            if (parent == null || parent.getLevel() != 1) {
                throw new RuntimeException("父级科室不存在或不是一级科室");
            }
        }

        Department department = new Department();
        department.setDepartmentName(dto.getDepartmentName());
        department.setLevel(dto.getLevel());
        department.setParentId(dto.getParentId());
        department.setCreateTime(new Date());

        return departmentDao.insert(department) > 0;
    }

    @Override
    @Transactional
    public boolean updateDepartment(DepartmentUpdateDTO dto) {
        Department existing = departmentDao.selectDepartmentById(dto.getDepartmentId());
        if (existing == null) {
            throw new RuntimeException("科室不存在");
        }

        // 验证父级科室是否存在
        if (dto.getLevel() == 2 && dto.getParentId() != null) {
            Department parent = departmentDao.selectDepartmentById(dto.getParentId());
            if (parent == null || parent.getLevel() != 1) {
                throw new RuntimeException("父级科室不存在或不是一级科室");
            }
        }

        existing.setDepartmentName(dto.getDepartmentName());
        existing.setLevel(dto.getLevel());
        existing.setParentId(dto.getParentId());

        return departmentDao.updateDepartment(existing) > 0;
    }

    @Override
    @Transactional
    public boolean deleteDepartment(Integer id) {
        Department department = departmentDao.selectDepartmentById(id);
        if (department == null) {
            throw new RuntimeException("科室不存在");
        }

        // 检查是否有子科室
        List<Department> children = departmentDao.selectChildrenByParentId(id);
        if (!children.isEmpty()) {
            throw new RuntimeException("该科室下有子科室，无法删除");
        }

        // 检查是否有诊室关联
        List<Room> rooms = roomDao.selectRoomsByDepartmentId(id);
        if (!rooms.isEmpty()) {
            throw new RuntimeException("该科室下有关联诊室，无法删除");
        }

        // 检查是否有特色门诊关联
        List<SpecialClinic> clinics = specialClinicDao.getSpecialClinicsByDepartmentId(id);
        if (!clinics.isEmpty()) {
            throw new RuntimeException("该科室下有关联特色门诊，无法删除");
        }

        return departmentDao.deleteDepartmentById(id) > 0;
    }

    @Override
    public List<DepartmentDTO> getAllDepartments() {
        List<Department> departments = departmentDao.selectAll();
        return departments.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    public List<RoomDTO> getRoomsByDepartmentId(Integer departmentId) {
        List<Room> rooms = roomDao.selectRoomsByDepartmentId(departmentId);
        return rooms.stream()
                .map(this::convertToRoomDTO)
                .collect(Collectors.toList());
    }

    @Override
    public List<ClinicDTO> getClinicsByDepartmentId(Integer departmentId) {
        List<SpecialClinic> clinics = specialClinicDao.getSpecialClinicsByDepartmentId(departmentId);
        return clinics.stream()
                .map(this::convertToClinicDTO)
                .collect(Collectors.toList());
    }

    // 转换方法
    private DepartmentDTO convertToDTO(Department department) {
        DepartmentDTO dto = new DepartmentDTO();
        BeanUtils.copyProperties(department, dto);
        return dto;
    }

    private RoomDTO convertToRoomDTO(Room room) {
        RoomDTO dto = new RoomDTO();
        BeanUtils.copyProperties(room, dto);
        return dto;
    }

    private ClinicDTO convertToClinicDTO(SpecialClinic specialClinic) {
        ClinicDTO dto = new ClinicDTO();
        BeanUtils.copyProperties(specialClinic, dto);
        // 转换doctorIds为List
        if (specialClinic.getDoctorIds() != null) {
            dto.setDoctorIds(Arrays.asList(specialClinic.getDoctorIds().split(",")));
        }
        return dto;
    }
    @Override
    public List<Department> getDepartments() {
        List<Department> departments = departmentDao.selectAll();
        logger.info("查询到的科室列表数据：{}", departments);
        return departments;
    }

    @Override
    public Department getDepartmentById(int departmentId) {
        Department department = departmentDao.selectById(departmentId);
        logger.info("查询到的科室数据：{}", department);
        return department;
    }

    @Override
    public int addDepartment(Department department) {
        int result = departmentDao.insert(department);
        logger.info("新增科室结果：{}", result > 0 ? "成功" : "失败");
        return result;
    }

    @Override
    public int updateDepartment(Department department) {
        int result = departmentDao.updateById(department);
        logger.info("更新科室结果：{}", result > 0 ? "成功" : "失败");
        return result;
    }

    @Override
    public int deleteDepartment(int departmentId) {
        int result = departmentDao.deleteById(departmentId);
        logger.info("删除科室结果：{}", result > 0 ? "成功" : "失败");
        return result;
    }
}